﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Text.RegularExpressions;
using Util.Rand;
using Util.Net.Http;
using Util.Date;

namespace Util.Net.Stat
{
    public class StatCnzzCookie
    {
        public static string CookieKeyPrefix = "CNZZDATA";
        public static string CnzzIdKey = "cnzz_eid";

        public string CnzzKey { get; private set; } // 这个网站的唯一标识
        private string CnzzId { get; set; } // 当前访问者根据当前页面的id

        private DateTime VisitTime { get; set; } // 访问该页面的时间(刷新页面或进入子页面的时候也重置该时间)
        private DateTime LeftTime { get; set; } // 离开上一个页面的时间

        private DateTime EnterTime { get; set; } // 进入该页面的时间

        private Uri CurrentUri { get; set; } // 当前页面
        private Uri LastUri { get; set; } // 上一个页面

        private static Regex CnzzEnterTimeMatch = new Regex(@"this.n=""(?<time>\d+)""");

        private static int CurrentTimeTricksDivide = 1000 * 1000 * 10;
        private static int LeftTricksDivide = 1000 * 10;

        private CookieContainer Cookies { get; set; }
        private WebProxy Proxy { get; set; }

        private Cookie CnzzCookie { get; set; }

        public StatCnzzCookie(string cnzzKey, Uri currentUri, CookieContainer cookies, WebProxy proxy = null)
        {
            this.CnzzKey = cnzzKey;
            this.CurrentUri = currentUri;
            this.CnzzId = ((long)(Math.Floor(2147483648 * RandomUtility.RandomDouble()))).ToString();
            this.VisitTime = this.LeftTime = DateTime.Now;
            this.Cookies = cookies;
            this.Proxy = proxy;
            this.GetCnzzEnterTime(this.CurrentUri);
            this.AddCookie();
        }

        private void AddCookie()
        {
            this.CnzzCookie = new Cookie();

            this.CnzzCookie.Name = CookieKeyPrefix + this.CnzzKey;
            this.SetCookieValue();

            this.CnzzCookie.Path = "/";
            this.CnzzCookie.Domain = this.CurrentUri.Host;

            this.Cookies.Add(this.CnzzCookie);
        }

        private void SetCookieValue()
        {
            this.CnzzCookie.Value = CnzzIdKey + "%3D" + this.CnzzId + "-" + DateUtility.DateToTimestamp(this.EnterTime) / CurrentTimeTricksDivide + "-http%253A%252F%252F" + this.CurrentUri.Host + "%26ntime%3D" + DateUtility.DateToTimestamp(this.VisitTime) / CurrentTimeTricksDivide + "%26cnzz_a%3D0%26";
            if (this.LastUri != null)
            {
                this.CnzzCookie.Value += "sin%3Dhttp%253A%252F%252F" + this.LastUri.Host + "%252F%26";
            }
            this.CnzzCookie.Value += "ltime%3D" + DateUtility.DateToTimestamp(this.LeftTime) / LeftTricksDivide;
        }

        public void EnterTargetUri(Uri targetUri, string targetCnzzKey = null)
        {
            if (targetCnzzKey != null)
            {
                this.CnzzKey = targetCnzzKey;
            }

            this.LastUri = this.CurrentUri;
            this.CurrentUri = targetUri;

            this.GetCnzzEnterTime(this.CurrentUri);
            this.AddCookie();
        }

        private void GetCnzzEnterTime(Uri referUri)
        {
            HttpClient client = new HttpClient();
            client.Proxy = this.Proxy;
            client.CookieContainer = this.Cookies;
            client.Referer = referUri.AbsolutePath;
            try
            {
                string response = client.GetResponseString("http://s87.cnzz.com/stat.php?id=" + CnzzKey + "&web_id=" + CnzzKey + "&show=pic");
                Match match = CnzzEnterTimeMatch.Match(response);
                if (match.Success)
                {
                    long trick = long.Parse(match.Groups["time"].Value);
                    this.VisitTime = this.EnterTime = DateUtility.TimestampToDate(trick * CurrentTimeTricksDivide);
                }
                client.GetResponseString("http://c.cnzz.com/core.php?web_id=" + this.CnzzId + "&show=pic&t=z");
            }
            catch (Exception)
            {
                this.EnterTime = DateTime.Now;
            }
        }

        public void RefreshCurrentUri()
        {
            this.VisitTime = DateTime.Now;
            this.SetCookieValue();
        }
    }
}
